//This clock steals timing relations from the famous pardusclock by Spoilerhead
//http://stud3.tuwien.ac.at/~e0326004/pardus/pardusclock/onlineclock/clock.html
//
//Spoilerheads script is licenced under GPL2, so I guess this is also ;)
//
// - Jirina
//

function POGetClock () {
    var c = top.po_clock;
    if (c == null || c == undefined) {
        c = top.po_clock = new POClock;
        setInterval("POClockTick()",1000);
        c.updateElements = new Array ();
    } 
    return c;
    //document.getElementById("my_tim").innerHTML = c.getTime();
    //document.getElementById("my_gmt").innerHTML = c.getGMT();
    //document.getElementById("my_ap").innerHTML = c.getAPS();
    //document.getElementById("my_bui").innerHTML = c.getBuildingTime();
    //document.getElementById("my_pl").innerHTML = c.getPLTime();
    //document.getElementById("my_sb").innerHTML = c.getStarbaseTime();
}
top.POGetClock = POGetClock;

function POClock(){
    this.time = new Date;
    this.pardus_time = this.getPardusTime();
}

function POClockTick () {
    c = POGetClock ();
    c.clockTick ();
}

POClock.prototype.updateElements = null;

POClock.prototype.createTimeElement = function (key, element, type, compact, update, realtime, prefix, postfix) {
    if (!update) {
        var reg = {};
        reg.element = element;
        reg.compact = compact==null?false:compact;
        reg.prefix = prefix==null?"":prefix;
        reg.postfix = postfix==null?"":postfix;
        this.tickElement (reg);   
        return element;
    }
    
    var reg = this.getElementByKey (key);
    if (!reg) {
        reg = {};
        reg.key = key;
        this.updateElements.push (reg);
    }

    reg.element = element;
    reg.type = type;
    reg.realtime = realtime;
    reg.compact = compact==null?false:compact;
    reg.prefix = prefix==null?"":prefix;
    reg.postfix = postfix==null?"":postfix;
    this.tickElement (reg);
    
    return element;
}

POClock.prototype.getElementByKey = function (key) {
    var els = this.updateElements;
    for (var i=0; i<els.length; i++) {
        var reg = els[i];
        if (reg.key == key) return reg;
    }
    return null;
}

POClock.prototype.tickElements = function (realtimeOnly) {
    var els = this.updateElements;
    for (var i=0; i<els.length; i++) {
        var reg = els[i];
        if (realtimeOnly && !reg.realtime) continue;
        this.tickElement (reg);
    }
}

POClock.prototype.tickElement = function (reg) {
    var options = {};
    options.compact = reg.compact;
    reg.element.textContent = reg.prefix + this.getTimeType(reg.type, options) + reg.postfix;
    
    if (options.coloring_off != true) {
        if (options.countdown == true) {
            reg.element.style.color = "red";
        } else if (options.resolution == "minute") {
            reg.element.style.color = "lightskyblue";
        } else if (options.resolution == "second") {
            reg.element.style.color = "orange";
        }
    }
}

POClock.prototype.getTimeType = function (type, options) {
    switch (type) {
        case "getTime": return this.getTime(options);
        case "getGMT": return this.getGMT(options);
        case "getAPS": return this.getAPS(options);
        case "getBuildingTime": return this.getBuildingTime(options);
        case "getPLTime": return this.getPLTime(options);
        case "getStarbaseTime": return this.getStarbaseTime(options);
        case "getNPCTime": return this.getNPCTime(options);
        case "getLeechTime": return this.getLeechTime(options);
        case "getACSTime": return this.getACSTime(options);
        case "getEMTime": return this.getEMTime(options);
        case "getLSMTime": return this.getLSMTime(options);
        case "getLSATime": return this.getLSATime(options);
		case "getDruggyEff": return this.getDruggyEff(options);
		case "getDruggyTime": return this.getDruggyTime(options);
    }
    return type + " - undefined";
}

POClock.prototype.clockTick = function () {
    this.time = new Date;
    this.pardus_time = this.getPardusTime();
    this.tickElements (true);
}

POClock.prototype.prettyTime = function(h,m,s,options){
    var compact = false;
    if (options) {
        if (options.compact == true) compact = true;
    }
    
    //pad with zeroes if needed
    hours = (h > 9) ? "" + h : "0" + h;
    minutes = (m > 9) ? "" + m : "0" + m;
    seconds = (s > 9) ? "" + s : "0" + s;
    
    if (h != 0) {
        options.resolution = "hour";
    } else {
        if (m > 0) options.resolution = "minute";
        else options.resolution = "second";
    }
    
    if (compact) {
        if (h != 0) {
            return hours + ":" + minutes;
        } else {
            return minutes + ":" + seconds;
        }
    } else {
        return hours + ":" + minutes + ":" + seconds;
    }
}

POClock.prototype.getPardusTime = function(){
    // Return the pardus-time, which is 25 minutes late
    var my_time = new Date;
    var hours = my_time.getHours();
    var minutes = my_time.getMinutes();

    var min = minutes - 25;
    if( min < 0 )
    {
            min += 60;
            hours--;
    }

    if( hours < 0 )
    {
            hours = 23;
    }

    my_time.setMinutes(min);
    my_time.setHours(hours);

    return my_time;
}

POClock.prototype.getTime = function(options){
    var hours = this.time.getHours() % 24;
    var minutes = this.time.getMinutes();
    var seconds = this.time.getSeconds();

    options.coloring_off = true;
    
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getGMT = function(options){
    var gmtHours = this.time.getTimezoneOffset()/60;
    var hours = (this.time.getHours()+gmtHours) % 24;
    var minutes = this.time.getMinutes();
    var seconds = this.time.getSeconds();

    options.coloring_off = true;
    
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getAPS = function(options){
    var hours = 0;
    var minutes = 5 - this.time.getMinutes() % 6;
    var seconds = 59 - this.time.getSeconds();

    if (hours == 0 && minutes == 0) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getBuildingTime = function(options){
    var gmtHours = this.pardus_time.getTimezoneOffset()/60;
    var hours = this.pardus_time.getHours();
    var minutes = 59 - this.pardus_time.getMinutes();
    var seconds = 59 - this.pardus_time.getSeconds();

    hours += (gmtHours + 5);
    hours = 5 - (hours % 6);

    if (hours == 0 && minutes < 30) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getPLTime = function(options){
    var gmtHours = this.pardus_time.getTimezoneOffset()/60;
    var hours = this.pardus_time.getHours();
    var minutes = 59 - this.pardus_time.getMinutes();
    var seconds = 59 - this.pardus_time.getSeconds();

    hours += (gmtHours + 5);
    hours = 2 - ((hours + 2) % 3);

    if (hours == 0 && minutes < 30) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getStarbaseTime = function(options){
    var gmtHours = this.pardus_time.getTimezoneOffset()/60;
    var hours = this.pardus_time.getHours();
    var minutes = 59 - this.pardus_time.getMinutes();
    var seconds = 59 - this.pardus_time.getSeconds();

    hours += (gmtHours + 5);
    hours = 2 - ((hours + 1) % 3);
    if (hours == 0 && minutes < 30) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getStarbaseTimeFrom = function(time){
    var gmtHours = time.getTimezoneOffset()/60;
    var hours = time.getHours();
    var minutes = 59 - time.getMinutes();
    var seconds = 59 - time.getSeconds();
    var diff = new Date ();

    hours += (gmtHours + 5);
    hours = 2 - ((hours + 1) % 3);

    diff.setTime ((seconds*1000)+(minutes*60000)+(hours*3600000));
    return diff;
}

POClock.prototype.getNPCTime = function(options){
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = 8 - this.time.getMinutes() % 9;
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getLSATime = function(options){
    // Lucidi Squads, z15 scout and z16 fighter NPCs will attack you here
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = 0;
    
    seconds ++;
    if (seconds == 60) seconds = 0;
    
    if (seconds < 15) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    
    return this.prettyTime(hours, minutes, seconds, options);
}


POClock.prototype.getLSMTime = function(options){
    // Lucidi Squads, z15 scout and z16 fighter NPCs move here.
    // All other NPCs move according to the getNPCTime
    // h:mm ... x:08, x:17, x:26, x:33, x:41, x:51, x:59
    // Source: http://www.thewaistelands.info/pardus-clock/
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = this.time.getMinutes();
    
    var _minsToGo = 88;
    if (minutes < 26) { // move is x:08 or x:17 or x:26
        if (minutes < 8) { // move is x:08
                _minsToGo = 7 - minutes;
        } else 
        if (minutes < 16) { // move is x:17
                _minsToGo = 16 - minutes;
        } else { // move is x:26
                _minsToGo = 25 - minutes;
        }
    } else {
        if (minutes < 33) { // next move is at x:33
                _minsToGo = 32 - minutes;
        } else
        if (minutes < 41) { // next move is at x:41
                _minsToGo = 40 - minutes;
        } else
        if (minutes < 51) { // next move is at x:51
                _minsToGo = 50 - minutes;
        } else
        if (minutes < 59) { // next move is at x:59
                _minsToGo = 58 - minutes;
        } else { // next move is at x:08
                _minsToGo = 8;
        }
    }
    
    seconds ++;
    if (seconds == 60) {
        seconds = 0;
        _minsToGo ++;
    }
    
    if (seconds < 15 && _minsToGo == 0) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    
    return this.prettyTime(hours, _minsToGo, seconds, options);
}

POClock.prototype.getLeechTime = function(options){
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = 19 - this.time.getMinutes() % 20;
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getEMTime = function(options){
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = 59 - this.time.getMinutes() % 60 + 31;
    if (minutes >= 60) {
        minutes = minutes - 60;
    }
    if (hours == 0 && minutes < 10) {
        options.countdown = true;
    } else {
        options.countdown = false;
    }
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getACSTime = function(options){
    hours = 0;
    seconds = 59 - this.time.getSeconds();
    minutes = 0;
    return this.prettyTime(hours, minutes, seconds, options);
}

POClock.prototype.getSBTicksSince = function(lastTime){
    var nowms = this.pardus_time.getTime ();
    var timeoutMs = this.getStarbaseTimeFrom(lastTime).getTime (); // Time between LastTime and the first SB Tick following LastTime
    var lastMs = lastTime.getTime();

    // If the difference between Now and LastTime is smaller than what the time-to-tick was at last time,
    // we can safely say that there was no tick until last time.
    // E.g. LastTime=5PM, Now=6PM, SBTick=7PM
    if ((nowms - lastMs) < timeoutMs) return 0;
    else {
        // OK, now we simply count amount of whole 3h intervals between Now and LastTime
        // This will give us a 'base' value. The real number of ticks can then be either
        // the base value or base+1. This depends on how is the Last-Now interval positioned
        // against the SB ticking.
        var hourMs = 3*3600000 // 3 hours in milliseconds
        var ticksBase = Math.floor((nowms - lastMs) / hourMs);
        // In case the ticksBase is zero, the real ticks can be euther 0 or 1 (see comment above)
        // but the 0-case is already covered in the very first condition so now the
        // only possibility os 1
        if (ticksBase == 0) return 1;
        
        // OK, now we have to decide if the Now-Last spans tickBase or tickBase+1 ticks.
        // Let's take the easiest example - 1 or 2 ticks. In both cases the Now-Last is more than 3 hours
        // 1) Tick:5PM, Last:3PM, Now:7PM - Now-Last:4h, Ticks:1, Timeout:2h
        // 2) Tick:5PM,8PM, Last:4:30PM, Now:8:30PM - Now-Last:4h, Ticks:2, Timeout:0.5h
        // So... we have to check if the Now-Last spans both ticks or only the first one.
        // 1) (2h+(3h*1)) < (7h-4h)       => 5h < 3h   => FALSE - it only spans one tick
        // 2) (0.5h+(3h*1)) < (8:30-4:30) => 3.5h < 4h => TRUE - it spans two ticks
        if ((timeoutMs + (hourMs*ticksBase)) < (nowms - lastMs)) {
            return ticksBase + 1;
        }
        
        return ticksBase;
    }
}


// For druggy display
POClock.prototype.updateDruggy = function(options){
	var overdrug = Number(localStorage.getItem ('po_druggy_overdrug'));
	var zeroDrugTime = Number(localStorage.getItem ('po_druggy_zeroDrugTime'));
	var drugTickTime = Number(localStorage.getItem ('po_druggy_tick'));
	var TCval = Number(localStorage.getItem ('po_druggy_TCval'));
	var curtime = new Date();
	var curtimeSec = curtime.getTime();
	var TCoverdrug;

	// Make sure they are valid
	if (overdrug==null)	overdrug = 0;
	if (zeroDrugTime==null)	zeroDrugTime = 0;	
    if (drugTickTime==null)	drugTickTime=3600;  // default to 1 hour	
	if (TCval==null) TCval = 0;
	
	drugTickTime = parseInt(drugTickTime) * 1000; // convert to ms because time is all in ms
	
	if (overdrug>0)
	{
		// check if we passed the drug tick...
		// expected overdrug = parseInt((zeroDrugTime - curtimeSec) / drugTickTime);
		overdrug = ((zeroDrugTime - curtimeSec) / drugTickTime);
		
		// if > 0, parseInt needs to be +1 - trust me.
		if (overdrug > 0) overdrug = parseInt(overdrug + 1);
		else overdrug = parseInt(overdrug);
	
		// If we have Trip Control/Meditation
		if ((overdrug - TCval) > 0)
		{
			curtime.setTime((zeroDrugTime-curtimeSec) - (TCval)*drugTickTime);
			//options.countdown = true;
		}	
		else if (overdrug>0)
		{
			curtime.setTime(zeroDrugTime-curtimeSec);
			//options.countdown = false;
		}
		else
		{
			overdrug = 0; // in case set negative.
			curtime.setTime(0);
			//options.countdown = false;
		}

		// save new value
		localStorage.setItem ('po_druggy_overdrug',overdrug);
	}
	else
	{
		// set time to zero when druggy done.
		curtime.setTime(0);
		//options.countdown = false;
	}

	// Not sure if this is bad - could just store in localStorage.  ???
    this.drugtime = curtime.getTime();
	this.overdrug = overdrug;	
	this.drugTCval = TCval;
}
// For druggy display
POClock.prototype.getDruggyEff = function(options){
    this.updateDruggy(options);

	if (this.overdrug > this.drugTCval) options.countdown = true;
	
    return parseInt(this.overdrug-this.drugTCval);
}

// For druggy display
POClock.prototype.getDruggyTime = function(options){
	var curtime = new Date();

    this.updateDruggy(options);
	
	curtime.setTime(this.drugtime);

	if (this.overdrug > this.drugTCval) options.countdown = false;
	
    var hours = curtime.getUTCHours();
    var minutes = curtime.getMinutes();
    var seconds = curtime.getSeconds();

    return this.prettyTime(hours, minutes, seconds, options);
}
POGetClock ();